package com.cy.ppj.comm.utils;

import com.cy.ppj.comm.constant.Constants;
import com.cy.ppj.model.domian.product.ProductAttachment;
import com.cy.ppj.model.domian.product.ProductDocs;
import com.cy.ppj.model.enums.*;
import com.cy.ppj.model.enums.Process;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Base64Utils;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @description: 工具
 * @author: Ocean
 * @create: 2018-07-20 20:08
 **/
@Slf4j
public class CommonUtils {

	public static void main(String[] args) {
		System.out.println(UUID.randomUUID().toString());
	}
	
    public static boolean isExcel2003(String filePath) {
        return filePath.matches("^.+\\.(?i)(xls)$");
    }

    public static boolean isExcel2007(String filePath) {
        return filePath.matches("^.+\\.(?i)(xlsx)$");
    }

    /**
     * 时间格式化：日期 --> 字符串
     *
     * @param date
     * @return
     */
    public static String dateFormat(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat(Constants.yyyy_MM_dd_HH_mm_ss);
        return sdf.format(date);
    }

    /**
     * 时间格式化：日期 --> 字符串 : yyyy年MM月dd日 HH:mm
     *
     * @param date
     * @return
     */
    public static String dateFormat2(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm");
        return sdf.format(date);
    }

    /**
     * 字符串转时间：字符串 --> 日期
     *
     * @param str
     * @return
     */
    public static Date parseDate(String str) {
        SimpleDateFormat sdf = new SimpleDateFormat(Constants.yyyy_MM_dd_HH_mm_ss);
        Date date = null;
        try {
            date = sdf.parse(str);
        } catch (ParseException e) {
            log.error("parseDate error:", e);
        }
        return date;
    }

    /**
     * 当前时间X小时后
     *
     * @return
     */
    public static Date addTime(int amount, int unit) {
        return addTime(new Date(), amount, unit);
    }


    public static Date addTime(Date date, int amount, int unit) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(unit, amount);
        return calendar.getTime();
    }

    /**
     * 判断是否微信客户端请求
     *
     * @param request
     * @return
     */
    public static boolean isWechatClient(HttpServletRequest request) {
        String userAgent = request.getHeader("user-agent");
        if (StringUtils.isEmpty(userAgent)) {
            return false;
        }
        return userAgent.toLowerCase().indexOf("micromessenger") > 0;

    }

    /**
     * 获取请求IP
     *
     * @param request
     * @return
     */
    public static String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    /**
     * md5
     *
     * @param value
     * @return
     */
    public static String md5(String value) {
        //对密码进行 md5 加密
        return DigestUtils.md5DigestAsHex(value.getBytes());
    }

    /**
     * 生成随机数
     *
     * @param scale
     * @return
     */
    public static String randomCode(int scale) {
        StringBuilder stringBuilder = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < scale; i++) {
            stringBuilder.append(random.nextInt(10));
        }
        return stringBuilder.toString();
    }

    /**
     * 短信验证码key
     *
     * @param mobile
     * @param smsType
     * @return
     */
    public static String smsCodeKey(String mobile, SmsType smsType) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(Constants.SMS_CODE);
        stringBuilder.append(mobile);
        stringBuilder.append("-");
        stringBuilder.append(smsType.name());
        return stringBuilder.toString();
    }

    public static Process getNextProcess(Process preProcess, List<Process> processes) {
        //产品流程排序,升序
        processes = processes.stream().sorted(Comparator.comparing(Process::getOrder)).collect(Collectors.toList());
        //获取当前流程
        Optional<Process> optional = processes.stream()
                //如果电核成功，跳过复议，找下一个
                .filter(p -> p.getOrder() > preProcess.getOrder()).findFirst();
        if (!optional.isPresent()) {
            return null;
        }
        return optional.get();
    }

    /**
     * 获取订单当前流程
     *
     * @param processes
     * @param applyStatus
     * @param orderStatus
     * @return
     */
    public static Process getCurrentProcess(List<Process> processes, ApplyStatus applyStatus, OrderStatus orderStatus) {
        Process currentProcess = null;
        if (ApplyStatus.REJECT.equals(applyStatus)) {
            //拒绝
            currentProcess = Process.getProcessByFailStatus(orderStatus);
        } else if (ApplyStatus.PROCESSING.equals(applyStatus)) {
            //处理中
            if (OrderStatus.REVIEW_WAIT.equals(orderStatus)) {
                //复议中
                currentProcess = Process.REVIEW;
            } else {
                //根据当前订单审核状态获取 上一步 审核流程
                Process preProcess = Process.getProcess(orderStatus);
                //根据上一步，取得当前流程
                currentProcess = CommonUtils.getNextProcess(preProcess, processes);
            }
        } else if (ApplyStatus.PASS.equals(applyStatus)) {
            //通过
            currentProcess = Process.getProcess(orderStatus);
        }
        return currentProcess;
    }

    /**
     * 时间相差天数 date2 - date1
     *
     * @param date1
     * @param date2
     * @return
     */
    public static int diffDays(Date date1, Date date2) {
        if (date1 == null || date2 == null) {
            return 0;
        }
        int days = (int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24));
        return days;
    }


    /**
     * base64 加盐加密
     *
     * @param value
     * @return
     */
    public static String md5Passwod(String value) {
        String salt = Constants.SLAT;
        value = Base64Utils.encodeToString(value.concat(salt).getBytes());
        value = md5(value.concat(salt));
        return value;
    }

    /**
     * 随机数
     *
     * @param length
     * @return
     */
    public static String randomNumber(int length) {
        Random random = new Random();
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < length; i++) {
            stringBuilder.append(random.nextInt(10));
        }
        return stringBuilder.toString();
    }

    public static ProductDocs getProductDosc(String context, DocsType type) {
        if (StringUtils.isEmpty(context)) {
            return null;
        }
        ProductDocs productDocs = new ProductDocs();
        productDocs.setType(type);
        productDocs.setContext(context);
        return productDocs;
    }

    public static ProductAttachment getProductAttachment(String path, ProductAttachmentType type) {
        if (StringUtils.isEmpty(path)) {
            return null;
        }
        ProductAttachment productAttachment = new ProductAttachment();
        productAttachment.setPath(path);
        productAttachment.setType(type);
        return productAttachment;
    }

    /**
     * 得到某天的开始时间
     *
     * @param date
     * @return
     */
    public static Date getDayStartTime(Date date) {
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 当月第一天
     *
     * @param date
     * @return
     */
    public static Date getMonthStartTime(Date date) {
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        return getMonthStartTime(calendar);
    }

    /**
     * 当月第一天
     *
     * @param calendar
     * @return
     */
    public static Date getMonthStartTime(Calendar calendar) {
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 当月最后一天
     *
     * @param date
     * @return
     */
    public static Date getMonthEndTime(Date date) {
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        return getMonthEndTime(calendar);
    }

    /**
     * 当月最后一天
     *
     * @param calendar
     * @return
     */
    public static Date getMonthEndTime(Calendar calendar) {
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 得到某天的结束时间
     *
     * @param date
     * @return
     */
    public static Date getDayEndTime(Date date) {
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        return calendar.getTime();
    }

    /**
     * 通过身份证号码判断性别
     *
     * @param idNo
     * @return
     */
    public static Sex getSexByIdNo(String idNo) {
        if (StringUtils.isEmpty(idNo)) {
            return Sex.UNKNOW;
        }
        int length = idNo.length();
        if (length == 15) {
            // 15位身份证号码
            String usex = idNo.substring(14, 15);
            if (Integer.parseInt(usex) % 2 == 0) {
                // 女
                return Sex.FEMALE;
            } else {
                // 男
                return Sex.MALE;
            }
        } else if (length == 18) {
            // 18位身份证号码
            String usex = idNo.substring(16).substring(0, 1);
            if (Integer.parseInt(usex) % 2 == 0) {
                // 女
                return Sex.FEMALE;
            } else {
                // 男
                return Sex.MALE;
            }
        } else {
            return Sex.UNKNOW;
        }
    }

    public static String bankCardFormat(String str, int last) {
        if (StringUtils.isEmpty(str)) {
            return null;
        }
        return "**** **** **** ".concat(str.substring(str.length() - last));
    }

    public static String bankCardLastFormat(String str, int last) {
        if (StringUtils.isEmpty(str)) {
            return null;
        }
        return str.substring(str.length() - last);
    }

    public static String idNoFormat(String str, int before, int last) {
        if (StringUtils.isEmpty(str)) {
            return str;
        }
        if(str.length() < 6) {
            return str;
        }
        String beforeStr = str.substring(0, before);
        String lastStr = str.substring(str.length() - last);
        return beforeStr.concat(" **** ").concat(lastStr);
    }

    public static String nameFormat(String str) {
        if(StringUtils.isEmpty(str)) {
            return str;
        }
        String lastStr = str.substring(str.length() - 1);
        if (str.length() < 3) {
            return "*".concat(lastStr);
        }
        String beforeStr = str.substring(0, 1);
        return beforeStr.concat("*").concat(lastStr);
    }

    /**
     * 带百分号的乘法
     *
     * @param a
     * @param b
     * @return
     */
    public static BigDecimal multiplyWithPercent(BigDecimal a, BigDecimal b) {
        return multiplyWithPercent(a, b, 2);
    }

    /**
     * 带百分号的乘法
     *
     * @param a
     * @param b
     * @param scale
     * @return
     */
    public static BigDecimal multiplyWithPercent(BigDecimal a, BigDecimal b, int scale) {
        return a.multiply(b).divide(new BigDecimal("100"), scale, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 获取季节
     *
     * @param month
     * @return
     */
    public static Integer getQuarter(int month) {
        if (month >= 1 && month <= 3) {
            return 1;
        } else if (month >= 4 && month <= 6) {
            return 2;
        } else if (month >= 7 && month <= 9) {
            return 3;
        } else if (month >= 10 && month <= 12) {
            return 4;
        }
        return null;
    }

    /**
     * 当季最后一天
     *
     * @param time
     * @return
     */
    public static Date getQuarterEndTime(Date time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        int month = calendar.get(Calendar.MONTH) + 1;
        int quarter = getQuarter(month);
        switch (quarter) {
            case 1:
                month = 3;
                break;

            case 2:
                month = 6;
                break;

            case 3:
                month = 9;
                break;

            case 4:
                month = 12;
                break;

            default:
                break;
        }
        calendar.set(Calendar.MONTH, month - 1);
        return getMonthEndTime(calendar);
    }

    /**
     * 当季第一天
     *
     * @param time
     * @return
     */
    public static Date getQuarterStartTime(Date time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        int month = calendar.get(Calendar.MONTH) + 1;
        int quarter = getQuarter(month);
        switch (quarter) {
            case 1:
                month = 1;
                break;

            case 2:
                month = 4;
                break;

            case 3:
                month = 7;
                break;

            case 4:
                month = 10;
                break;

            default:
                break;
        }
        calendar.set(Calendar.MONTH, month - 1);
        return getMonthStartTime(calendar);
    }

    /**
     * 获取月份
     *
     * @param time
     * @return
     */
    public static Integer getMonth(Date time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        int month = calendar.get(Calendar.MONTH) + 1;
        return month;
    }

    /**
     * 获取年份
     *
     * @param time
     * @return
     */
    public static Integer getYear(Date time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        int year = calendar.get(Calendar.YEAR);
        return year;
    }
    
    /**
     * 判断List是否为空
     * @param list
     * @return
     */
    public static boolean isEmpty(List<?> list) {
    	return (list == null || list.isEmpty());
    }
    
    /**
     * 判断一个对象是否为空
     * @param object
     * @return
     */
    public static boolean isEmpty(Object object) {
    	return (object == null || "".equals(object));
    }
    
    /**
     * 生成当前时间加上4位随机数的字符串，形式："yyyyMMddHHmmssSSS" + "xxxx"
     * 
     * @return
     */
    public static String getCurrentTimeAndRandomNumber() {
    	SimpleDateFormat sdf = new SimpleDateFormat(Constants.yyyyMMddHHmmssSSS);
    	return sdf.format(new Date()).concat(randomNumber(4));
    }
    
    /**
     * 利用正则表达式判断字符串是否是数字
     * 
     * @param str
     * @return
     */
    public static boolean isNumeric(String str){
        Pattern pattern = Pattern.compile("[0-9]*");
        Matcher isNum = pattern.matcher(str);
        if( !isNum.matches() ){
            return false;
        }
        return true;
    }
    
    /**
     * 根据身份证号码计算年龄 age
     * 
     * @param idNo
     * @return
     */
    public static int getAgeByIdNo(String idNo) {
    	int age = 0;
    	if(StringUtils.isEmpty(idNo)) {
    		return age;
    	}
    	
    	int leh = idNo.length();
        if (leh == 18) {
        	String dates = idNo.substring(6, 10);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
            String year = sdf.format(new Date());
            age = Integer.parseInt(year) - Integer.parseInt(dates);
        }
        
        return age;
    }

    /**
     * java Bean 转 map，使用 LinkedHashMap 保证输出顺序按照添加顺序一致
     * @param beanObj
     * @return java.util.LinkedHashMap<K,V>
     */
    public static <K, V> LinkedHashMap<K, V> bean2Map(Object beanObj) throws Exception {
        if(beanObj == null){
            return null;
        }
        LinkedHashMap<K, V> map = new LinkedHashMap<>();

        //获取所有的属性
        Field[] declaredFields = beanObj.getClass().getDeclaredFields();
        for (Field field : declaredFields) {
            //打破封装，设置可访问
            field.setAccessible(true);
            map.put((K)field.getName(), (V)field.get(beanObj));
        }
        return map;
    }

    /**
     * java Bean 转 map, key 全为大写字母，使用 LinkedHashMap 保证输出顺序按照添加顺序一致
     * @param beanObj
     * @return java.util.LinkedHashMap<K,V>
     */
    public static <K, V> LinkedHashMap<K, V> bean2MapUpperKey(Object beanObj) throws Exception {
        if(beanObj == null){
            return null;
        }
        LinkedHashMap<K, V> map = new LinkedHashMap<>();

        //获取所有的属性
        Field[] declaredFields = beanObj.getClass().getDeclaredFields();
        for (Field field : declaredFields) {
            //打破封装，设置可访问
            field.setAccessible(true);
            map.put((K)field.getName().toUpperCase(), (V)new BigDecimal(field.get(beanObj).toString()).multiply(new BigDecimal(10000)).setScale(2).toString());
        }
        return map;
    }

    /**
     * 最近三年
     * @param
     * @return java.util.List<java.lang.Integer>
     */
    public static List<Integer> getRecent3Year() {
        Date now = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
        int thisYear = Integer.parseInt(sdf.format(now));

        List<Integer> list = new ArrayList<>();
        list.add(thisYear);
        list.add(thisYear - 1);
        list.add(thisYear - 2);

        return list;
    }

    /**
     * 获取出生日期  yyyy年MM月dd日
     * @param IDCard
     * @return
     */
    public static String getBirthday(String IDCard){
        if(isEmpty(IDCard)) {
            return "";
        }
        String birthday="";
        String year="";
        String month="";
        String day="";
        if (IDCard.length() == 15){
        //15位身份证号
            // 身份证上的年份(15位身份证为1980年前的)
            year = "19" + IDCard.substring(6, 8);
            //身份证上的月份
            month = IDCard.substring(8, 10);
            //身份证上的日期
            day= IDCard.substring(10, 12);
        }else if(IDCard.length() == 18){
            //18位身份证号
            // 身份证上的年份
            year = IDCard.substring(6).substring(0, 4);
            // 身份证上的月份
            month = IDCard.substring(10).substring(0, 2);
            //身份证上的日期
            day=IDCard.substring(12).substring(0,2);
        }
        birthday=year+"年"+month+"月"+day+"日";

        return birthday;
    }
}
